<?php
defined('BASEPATH') OR exit('No direct script access allowed');


use GuzzleHttp\Client as HttpClient;

class shopbase{

    public $checklink=false;
    private $apihost;
    private $apikey;
    private $apipass;
    private $client;
    private $auth;

    public function __construct($param=array())
    {
        $this->apihost=$param["apihost"];
        $this->client = new HttpClient(['timeout'  => 40.0]);
        $this->auth = [$param["apikey"], $param["apipass"],'verify' => false];
        $this->checklink();
    }


    public function change_site($site)
    {
        $extra=json_decode($site["extra"],true);
        $this->apihost=$extra["apihost"];
        $this->auth = [$extra["apikey"], $extra["apipass"],'verify' => false];
        $this->checklink();
    }
    

    public function updatepro($pid,$newdata)
    {
        $path="/admin/api/2019-04/products/".$pid.".json";
        if(isset($newdata["title"]))
        {
            $new=["product"=>["id"=>$pid,"title"=>$newdata["title"]]];
            $this->api_query($path,"put",$new);
            return "ok";            
        }
        if(isset($newdata["price"]))
        {
            $pro=$this->getproduct($pid,"variants");
            if(isset($pro["product"]["variants"]) && count($pro["product"]["variants"])>0)
            {
                $new=["product"=>["id"=>$pid,"variants"=>[]]];
                foreach($pro["product"]["variants"] as $v)
                {
                    $new["product"]["variants"][]=["id"=>$v["id"],"price"=>$newdata["price"]];
                }
                $this->api_query($path,"put",$new);
                return "ok";
            }
            else
            {
                return "fail";
            }

        }
    }

    public function syncuser($page,$maxuid)
    {
        $return=["data"=>[]];
        $path="/admin/api/2019-04/customers.json?page=".$page;
        if($maxuid>0)
        {
            $path.="&since_id=".$maxuid;            
        }
        $result=$this->api_query($path,"get");
        $result=json_decode($result,true);
        if(!$result["customers"])
        {
            return $return;
        }
        foreach($result["customers"] as $user)
        {
            $newuser=[
                "id_customer"=>$user["id"],
                "firstname"=>$user["first_name"],
                "lastname"=>$user["last_name"],
                "email"=>$user["email"],
                "date_add"=>date("Y-m-d H:i:s",strtotime($user["created_at"]))
            ];
            $return["data"][]=$newuser;
        }
        return $return;
    }

    public function cancel($oid)
    {
        $path="/admin/api/2019-04/orders/".$oid."/cancel.json";
        $this->api_query($path,"post");
        $this->refund($oid);        
        return "ok";
    }

    private function orderinfo($orderid)
    {
        $path="/admin/api/2019-04/orders/{$orderid}.json";
        $info=$this->api_query($path);
        return json_decode($info,true);
    }

    private function refundcalculate($orderid,$orderinfo)
    {
        $path="/admin/api/2019-04/orders/{$orderid}/refunds/calculate.json";
        $data=["refund"=>[
            "currency"=>"USD",
            "shipping"=>["full_refund"=>"true"],
            "refund_line_items"=>[],
        ]];
        
        foreach($orderinfo["order"]["line_items"] as $item)
        {
            $data["refund"]["refund_line_items"][]=[
                "line_item_id"=>$item["id"],
                "quantity"=>$item["quantity"],
                "restock_type"=>"no_restock",
            ];
        }
        $result=$this->api_query($path,"post",$data);
        return json_decode($result,true);
    }

    private function refund($orderid)
    {
        $orderinfo=$this->orderinfo($orderid);
        $path="/admin/api/2019-04/orders/{$orderid}/refunds.json";
        $data=["refund"=>[
            "currency"=>"USD",
            "notify"=>"true",
            "note"=>"out of stock",            
            "shipping"=>["full_refund"=>"true"],
            "refund_line_items"=>[],
            "transactions"=>[]
        ]];
        foreach($orderinfo["order"]["line_items"] as $item)
        {
            $data["refund"]["refund_line_items"][]=[
                "line_item_id"=>$item["id"],
                "quantity"=>$item["quantity"],
                "restock_type"=>"no_restock",
            ];
        }
        $transactions=$this->refundcalculate($orderid,$orderinfo);
        $data["refund"]["transactions"][]=[
            "parent_id"=>$transactions["refund"]["transactions"][0]["parent_id"],
            "amount"=>$transactions["refund"]["transactions"][0]["amount"],
            "kind"=>"refund",
            "gateway"=>$transactions["refund"]["transactions"][0]["gateway"]
        ];
        $result=$this->api_query($path,"post",$data);
        return json_decode($result,true);
    }

    
    public function shiporder($oid,$tracknumber)
    {

        $path="/admin/api/2019-04/locations.json";
        $result=$this->api_query($path,"get");
        $result=json_decode($result,true);
        if(empty($result["locations"]))
        {
            return "nolocation";
        }
        $locationid=$result["locations"][0]["id"];
        $path="/admin/api/2019-04/orders/".$oid."/fulfillments.json";
        $data=[
            "fulfillment"=>[
                "location_id"=>$locationid,
                "tracking_number"=>$tracknumber,
                "tracking_urls"=>[
                    "https://www.trackingmore.com/choose-en-".$tracknumber.".html?"
                ],
                "notify_customer"=>"true"
            ]
        ];
        $this->api_query($path,"post",$data);
        return "ok";
    }


    public function checkwaitorder($waitorder)
    {
        return false;
    }

    public function syncorder($page,$maxoid)
    {
        $return=["data"=>[]];
        $path="/admin/api/2019-04/orders.json?page=".$page."&status=open&financial_status=paid";
        if($maxoid>0)
        {
            $path.="&since_id=".$maxoid;
        }
        $result=$this->api_query($path,"get");
        $result=json_decode($result,true);
        if(!$result["orders"])
        {
            return $return;
        }
        foreach($result["orders"] as $order)
        {
            $neworder=[
                "id_order"=>$order["id"],
                "id_customer"=>$order["customer"]["id"],
                "current_state"=>2,
                "reference"=>$order["order_number"],
                "total_paid"=>$order["total_price"],
                "firstname"=>$order["shipping_address"]["first_name"],
                "lastname"=>$order["shipping_address"]["last_name"],
                "phone"=>$order["shipping_address"]["phone"],
                "phone_mobile"=>"",
                "name"=>$order["shipping_address"]["country"],
                "iso_code"=>$order["shipping_address"]["country_code"],
                "stname"=>$order["shipping_address"]["province"],
                "postcode"=>$order["shipping_address"]["zip"],
                "stcode"=>$order["shipping_address"]["province_code"],
                "city"=>$order["shipping_address"]["city"],
                "address1"=>$order["shipping_address"]["address1"],
                "address2"=>isset($order["shipping_address"]["address2"])?$order["shipping_address"]["address2"]:"",
                "date_add"=>date("Y-m-d H:i:s",strtotime($order["created_at"])),
                "payment"=>$order["payment_gateway_names"][0],
                "products"=>[],
            ];
            foreach($order["line_items"] as $item)
            {
                $hand=$this->getproduct($item["product_id"],"handle,images");
                $newp=[
                    "product_name"=>$item["name"],
                    "product_quantity"=>$item["quantity"],
                    "product_price"=>$item["price"],
                    "product_id"=>$item["product_id"],
                    "image"=>$hand["product"]["images"][0]["src"],
                    "handler"=>"/products/".$hand["product"]["handle"],
                ];
                $neworder["products"][]=$newp;
            }
            $return["data"][]=$neworder;
        }
        return $return;
    }

    private function getproduct($pid,$fields="")
    {
        $path="/admin/api/2019-04/products/".$pid.".json";
        if($fields)
        {
            $path.="?fields=".$fields;
        }
        $result=$this->api_query($path,"get");
        $result=json_decode($result,true);
        return $result;
    }

    public function delproduct($pro)
    {
        $pid=$pro["rid"];
        $path="/admin/api/2019-04/products/".$pid.".json";
        $this->api_query($path,"delete");
        return "ok";
    }


    public function addproduct($product)
    {
        $formatproduct=$this->format_product($product);        
        $path="/admin/products.json";
        $result=$this->api_query($path,"post",$formatproduct);
        $result=json_decode($result,true);
        $pid=$result['product']['id'];
        $checkva=[];
        if(isset($product["option"]["vv"][0]) && isset($product["option"]["vv"][0]["image"]) && $product["option"]["vv"][0]["image"])
        {
            $i=0;
            foreach($product["option"]["vv"][0]["value"] as $k=>$v)
            {
                if($k<count($product["option"]["vv"][0]["image"]))
                {
                    $checkva[]=["val"=>$v,"src"=>$this->_refix_ali_imgurl($product["option"]["vv"][0]["image"][$k]),"vid"=>[]];
                }
            }

        }
        $imgs=$result['product']['images'];
        $key = array_rand($imgs,1);
        $randimgid=$imgs[$key]["id"];
        $randvid=[];
        $catch=0;
        foreach($result['product']['variants'] as $v)
        {
            $match=0;
            if($checkva)
            {
                foreach($checkva as $k=>$va)
                {
                    if($v["option1"]==$va["val"])
                    {
                        $checkva[$k]["vid"][]=$v["id"];
                        $match=1;
                        $catch=1;
                        break;
                    }                        
                }
                if($match==0)
                {
                    $randvid[]=$v["id"];
                }
            }
        }
        if($catch==1)
        {
            $this->addvaimg($checkva,$pid);
        }
        elseif($randvid)
        {
            $this->addrandvaimg($randvid,$pid,$randimgid);
        }
        return $pid;
    }

    private function addvaimg($checkva,$pid)
    {
        $path="/admin/products/".$pid."/images.json";
        if($checkva)
        {
            foreach($checkva as $item)
            {
                if($item["vid"])
                {
                    $img=["image"=>["src"=>$item["src"],"variant_ids"=>$item["vid"]]];
                    $this->api_query($path,"post",$img);
                }
    
            }    
        }

    }

    private function addrandvaimg($randvid,$pid,$randimgid)
    {
        $path="/admin/products/".$pid."/images/".$randimgid.".json";
        $img=["image"=>["id"=>$randimgid,"variant_ids"=>$randvid]];
        $this->api_query($path,"put",$img);        
    }

    private function _refix_ali_imgurl($url)
    {
        $url = str_replace(["ae01.alicdn.com","_50x50.jpg"],["picture.qdbeauty.com","_640x640.jpg"],$url);
        if(strstr($url,"_640x640"))
        {
            $tmp=explode("_640x640",$url);
            $url=$tmp[0];
        }
        return $url;
    }

    private function format_product($product)
    {
        $newproduct=array("product"=>array());
        $newproduct["product"]["title"]=$product["name"];
        $newproduct["product"]["metafields_global_description_tag"]=$product["meta"]?$product["meta"]:$product["name"];
        $newproduct["product"]["body_html"]=$product["desc"];
        if(empty($product["desc"]))
        {
            $newproduct["product"]["body_html"]=$product["name"];
        }
        else
        {
            $newproduct["product"]["body_html"]=$product["desc"];
        }
        $newproduct["product"]["vendor"]=$product["vendor"];
        $newproduct["product"]["product_type"]=$product["catename"];
        $newproduct["product"]["variants"]=array();
        $newproduct["product"]["options"]=array();

        $newproduct["product"]["images"]=array();
       
        if($product["tags"])
        {
            $newproduct["product"]["tags"]=substr(rtrim($product["tags"],","),0,200);
            $tmp_tag=explode(",",$newproduct["product"]["tags"]);
            array_pop($tmp_tag);
            $newtag=[];
            foreach($tmp_tag as $tag)
            {
                $tag=str_replace(["-","%","&","#"],"",$tag);
                
                if(empty(trim($tag))) continue;
                if(strstr($tag,"#")) continue;
                if(strstr($tag,"M/L/")) continue;
                if(strstr($tag,"M/L/")) continue;
                if(preg_match('/china/i',$tag)) continue;
                if(!in_array($tag,$newtag)) $newtag[]=$tag;
            }
            $newproduct["product"]["tags"]=implode(",",$newtag);
           
        }
        
        $compare_ratio=[1.3,1.35,1.4,1.45,1.5,1.55,1.6,1.65,1.7];

        if($product["option"] && isset($product["option"]["vv"]))
        {
            
            foreach($product["option"]["vv"] as $k=>$v)
            {
                $newproduct["product"]["options"][]=array("name"=>$v["name"],"values"=>$v["value"]);
            }
            
            if(count($product["option"]["vv"])==1)
            {
                $icount=0;
                $val_cons=array();
                foreach($product["option"]["vv"][0]["value"] as $k=>$val)
                {
                    if(in_array(strtolower($val),$val_cons))
                    {
                        $val=$val."_".mt_rand(100000,999999);
                    }
                    $val_cons[]=strtolower($val);

                    $price=$product["price"];
                    if(isset($product["option"]["vv"][0]["price"][$k]))
                    {
                        $price=$product["option"]["vv"][0]["price"][$k];
                    }

                    /*
                    if(isset($product["option"]["vc"][$icount]))
                    {
                        $price=$product["option"]["vc"][$icount];
                        if(isset($product["option"]["vd"]) && $product["option"]["vd"][$icount]!="true" && $product["option"]["vd"][$icount]!=1)
                        {
                            continue;
                        }
                    }
                    */
                    shuffle($compare_ratio);
                    $compareprice=sprintf("%.2f",$price*$compare_ratio[0]);
                    $newproduct["product"]["variants"][]=array("option1"=>$val,"price"=>$price,"taxable"=>"false","compare_at_price"=>$compareprice,"sku"=>$product["sku"]."-".$icount);
                    $icount++;
                    if($icount>100){
                       	break;
                    }
                }
            }
            else if(count($product["option"]["vv"])==2)
            {   
                $icount=0;
                $val_cons=array();
                foreach($product["option"]["vv"][0]["value"] as $k1=>$v1)
                {
                    if(in_array(strtolower($v1),$val_cons))
                    {
                        $v1=$v1."_".mt_rand(100000,999999);
                    }
                    $val_cons[]=strtolower($v1);
                    shuffle($compare_ratio);
                    
                    foreach($product["option"]["vv"][1]["value"] as $k2=>$v2)
                    {
                        if($icount>99){
                            break;
                        }

                        $price=$product["price"];

                        if(isset($product["option"]["vv"][0]["price"][$k1]))
                        {
                            $price=$product["option"]["vv"][0]["price"][$k1];
                        }
                        /*
                        
                        if(isset($product["option"]["vc"][$icount]))
                        {
                            $price=$product["option"]["vc"][$icount];
                            if(isset($product["option"]["vd"]) && $product["option"]["vd"][$icount]!="true" && $product["option"]["vd"][$icount]!=1)
                            {
                                continue;
                            }
                        }
                        */
                        
                        $compareprice=sprintf("%.2f",$price*$compare_ratio[0]);

                        $variant=array("option1"=>$v1,"option2"=>$v2,"price"=>$price,"taxable"=>"false","compare_at_price"=>$compareprice,"sku"=>$product["sku"]."-".$icount);
                        
                        $newproduct["product"]["variants"][]=$variant;
                        
                        $icount++;
                        
                    }                   
                }
            }
            
        }
        else
        {            
            $price=$product["price"];
            shuffle($compare_ratio);
            $compareprice=sprintf("%.2f",$price*$compare_ratio[0]);

            $newproduct["product"]["variants"][]=array("option1"=>"Default Title","price"=>$price,"taxable"=>"false","compare_at_price"=>$compareprice,"sku"=>$product["sku"].$product["tbid"]);
        }

        if($product["thumb"])
        {
            $icount=0;
            foreach($product["thumb"] as $img)
            {
                $newproduct["product"]["images"][]=array("src"=>$this->imgurl($img));
                /*
                $icount++;
                if(count($product["thumb"])>1 && $icount==1)
                {
                    $firstimg=array("src"=>$this->imgurl($img));
                    continue;
                }
                $newproduct["product"]["images"][]=array("src"=>$this->imgurl($img));
                if(count($product["thumb"])>1 && $icount==2)
                {
                    $newproduct["product"]["images"][]=$firstimg;
                }*/
            }
        }
        
        return $newproduct;
    }

    private function imgurl($url)
    {
        if(substr($url,0,4)!="http")
        {
            $url="http:".$url;
        }

        $url = str_replace("ae01.alicdn.com","picture.qdbeauty.com",$url);
        $url = str_replace("_50x50","_640x640",$url);
        if(strstr($url,"_640x640"))
        {
            $tmp=explode("_640x640",$url);
            return $tmp[0];
        }
        else
        {
            return $url;
        }        
    }


    public function synccatrgory($category)
    {
        $result=[];
        foreach($category as $cat)
        {
            if($cat["rid"]>0)
            {
                $this->updatecollect($cat["rid"],$cat["name"]);
            }
            else
            {
                $rid=$this->publishcat($cat["name"]);
                $result[$cat["id"]]=$rid;
            }
        }
        return $result;
    }

    public function delcatgory($cat)
    {
        $rid=$cat["rid"];
        if($rid>0)
        {
            $path="/admin/custom_collections/".$rid.".json";
            $this->api_query($path,"delete");
        }
    }

    private function updatecollect($rid,$name)
    {
        $path="/admin/custom_collections/".$rid.".json";
        $data=["custom_collection"=>["title"=>$name]];
        $this->api_query($path,"put",$data);        
    }

    private function publishcat($name)
    {
       
        $path="/admin/custom_collections.json";
        $data=["custom_collection"=>["title"=>$name]];
        $result=$this->api_query($path,"post",$data);
        $result=json_decode($result,true);
        return $result["custom_collection"]["id"];
    }

    private function api_query($path,$querymethod="get",$jsondata=[])
    {
        //$host="https://".$this->apikey.":".$this->apipass."@".$this->apihost;
        $host="https://".$this->apihost;
        $url=$host.$path;
        $errorcount=1;
        $maxerror=$errorcount;
        while($errorcount>0)
        {
            try
            {
                while(1)
                {
                    switch($querymethod)
                    {
                        case "get":
                            $res=$this->client->request('GET', $url, [
                                'auth' => $this->auth
                            ]);
                            $html_doc=$res->getBody();
                            break;
                        case "post":
                            $res=$this->client->request('POST', $url, [
                                'json' => $jsondata,
                                'auth' => $this->auth
                            ]);
                            $html_doc=$res->getBody();
                            break;
                        case "put":
                            $res=$this->client->request('PUT', $url, [
                                'json' => $jsondata,
                                'auth' => $this->auth
                            ]);
                            $html_doc=$res->getBody();                        
                            break;
                        case "delete":
                            $res=$this->client->request('DELETE', $url, [
                                'auth' => $this->auth
                            ]);
                            $html_doc=$res->getStatusCode();
                            break;
                    }

                    if(strstr($html_doc,"Exceeded 2 calls per second"))
                    {
                        sleep(1);
                        continue;
                    }
                    else
                    {
                        return $html_doc;                        
                    }
                }
            }   
            catch (Exception $e) {
                echo $url."\n";
                echo '请求异常，重试...'.($maxerror-$errorcount+1).'/'.$maxerror.'...'."\n";
                echo $e->getMessage();
                echo "\n";
                $errorcount--;
            }
        }
    }

    private function checklink()
    {
        $path="/admin/pages.json";
        $data=$this->api_query($path);
        $result=json_decode($data,true);
        if(isset($result["pages"]))
        {
            $this->checklink=true;
        }
    }
    
}